<template>
  <div class="component-image-preview">
    <!-- 图片预览列表 -->
    <div class="image-preview-list">
      <!-- 已上传的图片项 -->
      <div v-for="(file, index) in fileList" :key="file.ossId" class="image-item">
        <el-image
          :src="file.url"
          fit="cover"
          class="image-thumb"
          @click="handlePreview(file.url)"
          preview-teleported
        >
          <template #error>
            <div class="image-error">加载失败</div>
          </template>
        </el-image>
        <el-icon class="image-delete" @click="handleDelete(index)">
          <Close />
        </el-icon>
      </div>

      <!-- 上传占位框（仅当数量未达到 limit 时显示） -->
      <div
        v-if="fileList.length < limit"
        class="image-item upload-placeholder"
        @click="handleUploadClick"
      >
        <el-icon class="upload-icon"><Plus /></el-icon>
      </div>
    </div>

    <!-- 图片预览弹窗 -->
    <el-dialog v-model="dialogVisible" title="图片预览" width="800px" append-to-body>
      <img :src="dialogImageUrl" style="display: block; max-width: 100%; margin: 0 auto" />
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue'
import { OssVO } from '@/api/system/oss/types'
import { staticService } from '@/utils/ruoyi';

// ------------------- Props -------------------
const props = defineProps({
  imageList: {
    type: Array as () => OssVO[],
    default: () => []
  },
  // 最大图片数量，达到后隐藏上传按钮
  limit: {
    type: Number,
    default: Infinity
  }
})

const emit = defineEmits<{
  (e: 'update:modelValue', value: OssVO[]): void
  (e: 'upload-click'): void // 触发父级上传逻辑
  (e: 'update:imageList', value: OssVO[]): void;     // 更新图片列表
}>()

// ------------------- 响应式数据 -------------------
const fileList = ref<OssVO[]>([])
const dialogImageUrl = ref('')
const dialogVisible = ref(false)

// 监听传入的图片列表
watch(
  () => props.imageList,
  (val) => {
    if (Array.isArray(val)) {
      fileList.value = [...val]
    } else {
      fileList.value = []
    }
  },
  { immediate: true, deep: true } // 添加 deep: true 选项
)
// 初始化时同步父组件的数据
onMounted(() => {
  fileList.value = [...props.imageList];
});

// ------------------- 删除图片 -------------------
const handleDelete = (index: number) => {
  fileList.value.splice(index, 1)
  emit('update:imageList', fileList.value);
}

// ------------------- 预览图片 -------------------
const handlePreview = (url: string) => {
  dialogImageUrl.value = staticService(url)
  dialogVisible.value = true
}

// ------------------- 触发上传（通知父组件）-------------------
const handleUploadClick = () => {
  emit('upload-click') // 触发父组件定义的上传方法
}
</script>

<style lang="scss" scoped>
.component-image-preview {
  .image-preview-list {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
  }

  .image-item {
    position: relative;
    width: 100px;
    height: 100px;
    border: 1px solid #ddd;
    border-radius: 4px;
    overflow: hidden;
    background-color: #f5f5f5;

    &:hover {
      .image-delete {
        opacity: 1;
      }
    }
  }

  .image-thumb {
    width: 100%;
    height: 100%;
    cursor: pointer;
  }

  .image-error {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 100%;
    font-size: 12px;
    color: #999;
    background-color: #eee;
  }

  .image-delete {
    position: absolute;
    top: 4px;
    right: 4px;
    background-color: rgba(0, 0, 0, 0.5);
    color: #fff;
    border-radius: 50%;
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.3s;
    cursor: pointer;
  }

  // 上传占位框样式
  .upload-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    border: 1px dashed #c0ccda;
    background-color: #fafafa;

    &:hover {
      border-color: #1890ff;
    }
  }

  .upload-icon {
    font-size: 24px;
    color: #999;
  }
}
</style>
